﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Zatify.WebUI.Infrastructure.Filters;
using Zatify.WebUI.Infrastructure;
using Zatify.Domain.Abstract;
using Zatify.WebUI.Admin.Models;
using Zatify.Domain.Data;
using System.Linq.Expressions;
using Zatify.WebUI.Infrastructure.Absrtact;
using Zatify.WebUI.Models;

namespace Zatify.WebUI.Areas.Admin.Controllers
{
    [ZatifyAdminAuthorizeAttribute]
    [Utils.MyRequireHttps]
    public class UsersController : AdminBaseController
    {
        private const int PageSize = 20;

        private IZatifyRepository repository;

        protected override AdminModules AdminModule
        {
            get
            {
                return AdminModules.Users;
            }
        }

        public UsersController(IZatifyRepository repository, IZatifyAuthProvider authProvider)
        {
            this.repository = repository;
        }

        public ActionResult List(string sortOrder, int page = 1, int id = 0, SearchUserViewModel searchUserModel = null)
        {
            double timeZoneOffset = this.User.TimeZoneOffset;

            Func<User, bool> searchByUserId = (u => !String.IsNullOrEmpty(searchUserModel.UserID) ? u.Login.Trim().ToLower().Contains(searchUserModel.UserID.Trim().ToLower()) : true);
            Func<User, bool> searchByEmail = (u => !String.IsNullOrEmpty(searchUserModel.Email) ? u.Email.Trim().ToLower().Contains(searchUserModel.Email.Trim().ToLower()) : true);
            Func<User, bool> searchByPhone = (u => !String.IsNullOrEmpty(searchUserModel.Phone) ? u.Phone.Trim().ToLower().Contains(searchUserModel.Phone.Trim().ToLower()) : true);

            var users = SortUsers(repository.Users, sortOrder ?? "RegDate desc").Where(searchByUserId).Where(searchByEmail).Where(searchByPhone).Skip((page - 1) * PageSize).Take(PageSize).ToList();

            users.ForEach(u =>
            {
                u.DateAdded = u.DateAdded.AddMinutes(-timeZoneOffset);
            });

            var model = new UsersListViewModel()
            {
                CurrentUserRole = User.UserRole,

                SelectedUserID = id,
                Users = users,
                PagingInfo = new PagingInfo()
                {
                    TotalItems = repository.Users.Where(searchByUserId).Where(searchByEmail).Where(searchByPhone).Count(),
                    ItemsPerPage = PageSize,
                    CurrentPage = page,
                },
                SearchModel = searchUserModel,
                SortOrder = (sortOrder == "RegDate" ? "RegDate" : "RegDate desc")
            };

            var pages = new List<SelectListItem>();

            for (int i = 1; i <= model.PagingInfo.TotalPages; i++)
                pages.Add(new SelectListItem() { Text = i.ToString(), Value = i.ToString(), Selected = (i == page) });

            ViewData["pagesCount"] = pages;

            return View(model);
        }

        private IQueryable<User> SortUsers(IQueryable<User> users, string sortOrder)
        {
            switch (sortOrder)
            {
                case "RegDate":
                    return users.OrderBy(u => u.DateAdded);
                case "RegDate desc":
                    return users.OrderByDescending(u => u.DateAdded);

                default:
                    return users;
            }
        }

        [HttpPost]
        public ActionResult Update(User user, SearchUserViewModel searchUserModel, int page = 1)
        {
            user.Email = user.Email ?? String.Empty;
            user.Phone = user.Phone ?? String.Empty;
            user.RegState = user.RegState ?? String.Empty;
            user.RegCity = user.RegCity ?? String.Empty;

            if (this.ModelState.IsValid)
            {
                repository.UpdateUser(user);
            }
            else
            {
                ViewData["Error"] = "Error occured during User save";
            }

            return RedirectToAction("List", new
            {
                page = page,
                //searchUserModel = searchUserModel
                userID = searchUserModel.UserID,
                email = searchUserModel.Email,
                phone = searchUserModel.Phone
            });
        }

        [HttpPost]
        public ActionResult Add(AddNewUserViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new User()
                {
                    Login = model.UserID,
                    Password = model.Password,
                    Email = !String.IsNullOrWhiteSpace(model.Email) ? model.Email : String.Empty,
                    Phone = !String.IsNullOrWhiteSpace(model.Phone) ? model.Phone : String.Empty
                };

                repository.AddUser(user);

                return RedirectToAction("List");
            }
            else
            {
                return Json(false);
            }
        }

        public JsonResult UserIDUnique(string userId)
        {
            if (repository.Users.Any(u => u.Login.ToLower() == userId.ToLower()))
                return Json(userId + " is already in use.", JsonRequestBehavior.AllowGet);
            else
                return Json(true, JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public ActionResult ChangePassword(ChangeUserPasswordViewModel model)
        {
            if (ModelState.IsValid)
            {
                repository.UserChangePassword(model.UserID, model.Password);

                return RedirectToAction("List");
            }
            else
            {
                return Json(false);
            }
        }

        public ActionResult Delete(int id)
        {
            if (id > 0)
                repository.UserDeleteById(id);

            return RedirectToAction("List");
        }

        public ActionResult DeleteUsers(int[] usersIds)
        {
            if (usersIds != null && usersIds.Length > 0)
            {
                repository.UsersDeleteByIds(usersIds);
                return Json(new { status = true });
            }
            else
            {
                return Json(new { status = false });
            }
        }

        public ActionResult ChangeUserStatus(int id, int activate)
        {
            if (activate == 0 || activate == 1)
                repository.UserChangeStatus(id, (activate == 1));

            return RedirectToAction("List");
        }

        public ActionResult ChangeUsersStatus(int[] usersIds, int activate)
        {
            if ((usersIds != null && usersIds.Length > 0))
            {
                if (activate == 0 || activate == 1)
                    repository.UsersChangeStatus(usersIds, activate == 1);

                return Json(new { status = true });
            }
            else
            {
                return Json(new { status = false });
            }
        }
    }
}
